package main

import (
	"fmt"
	"time"
)

// Write Data 写数据
func writeData(intChan chan int) {
	for i := 0; i < 50; i++ {
		intChan <- i
		fmt.Println("写到的数据===>", i)
	}
	close(intChan)
}

// Read Data 读数据
func readData(intChan chan int, exitChan chan bool) {
	for {
		v, ok := <-intChan
		if !ok {
			break
		}
		fmt.Println("读到的数据===>", v)
	}
	exitChan <- true
	close(exitChan)

}

// 正常函数
func sayHello() {
	for i := 0; i < 10; i++ {
		time.Sleep(time.Millisecond)
		fmt.Println("hello world~")
	}
}

// 可能出错函数
func test() {
	// defer+recover
	defer func() {
		// 捕获test()抛出的panic
		if err := recover(); err != nil {
			fmt.Println("test()发生错误,", err)
		}
	}()
	var myMap map[int]string
	myMap[0] = "golang"
}

func main() {
	// 创建两个管道
	/*intChan := make(chan int, 50)
	exitChan := make(chan bool, 1)

	// 创建协程
	go writeData(intChan)
	go readData(intChan, exitChan)

	// 设置阻塞条件
	for {
		_, ok := <-exitChan
		if !ok {
			break
		}
	}

	// 管道可以声明为只读，或只写
	// 默认情况下，管道是双向的
	// 声明只写
	var chan1 chan<- int
	chan1 = make(chan int, 3)
	chan1 <- 10
	//num:= <- 20 错误，不可读
	println(chan1)

	// 声明只写
	var chan2 <-chan int
	//chan2 <- 10 错误，不可写
	num := <-chan2
	println(num)*/

	/*// 使用select可以解决从管道中取数据的阻塞问题
	// 1、定义一个管道10个数据int
	intChan := make(chan int, 10)
	for i := 0; i < 10; i++ {
		intChan <- i
	}
	// 2、定义一个管道 5个数据string
	stringChan := make(chan string, 5)
	for i := 0; i < 5; i++ {
		stringChan <- "hello" + fmt.Sprintf("%d", i)
	}

	//select 方法解决
	//label:
	for {
		select {
		case val := <-intChan:
			fmt.Println(val)
		case val := <-stringChan:
			fmt.Println(val)
		default:
			fmt.Println("都取不到数据，退出吧")
			return
			//break label //退出方法break


		}
	}*/

	// 使用defer+recover捕获可能出错的函数
	go sayHello()
	go test()

	for i := 0; i < 10; i++ {
		fmt.Println("main() ok=", i)
		time.Sleep(time.Millisecond)
	}
}
